/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package xml.parserDOM;

import Clases.Atributo;
import Clases.Tag;
import java.io.File;
import java.io.IOException;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import xml.parserSAX.SAXException;
import xml.io.xmlReader;
import xml.parserSAX.SAXHandler;
/**
 *
 * @author Lucas
 */
public class DOMParser {
    public Arbol tree = null;
    
    public DOMParser(String fp, SAXHandler sax) throws SAXException, IOException
    {
            tree = parserXML(new File(fp), sax);
    }


    public Arbol parserXML(File file, SAXHandler sax) throws SAXException, IOException
    {
        //Lista para asiganacion de hijos a padres.
	ArrayList<xml.parserDOM.Nodo<Tag>> pila = new ArrayList<Nodo<Tag>>();
        //Leo el archivo para ser procedo a un string
        String doc[] = xmlReader.read(file);
        boolean isFirst = true;
        Arbol arbol = new Arbol();
        //arbol = null;
        String regex = "<\\?xml.*>|<(\\w+)>|<(\\w+) (\\w+)=\"(\\w+)\">|</(\\w+)>|<!DOCTYPE (\\w+) SYSTEM \"(.*)\">|<!-- (\\w+)";
        //compilamos el patron
        Pattern pattern = Pattern.compile(regex);

        // recorro el archivo xml linea a linea
        Integer countLine =0;
        for (String line : doc)
        {
            countLine++;
            Matcher matcher = pattern.matcher(line);
            matcher.find();
            //creo el nodo
            Nodo<Tag> nodo = new Nodo<Tag>();
            Tag tag = new Tag();
            Atributo atr;
            //controla los tag sin atributos
            try {
                if (matcher.group(1) != null) {
                    //asigano el nombre del tag al tag
                    tag.setQname(matcher.group(1));
                    nodo.setTag(tag);
                    //asigano a la pila el nodo creado;
                    pila.add(nodo);

                    sax.startElement(matcher.group(1).toString(), null);
                    if (isFirst) {
                            // creo un arbol para tag sin atributos

                            isFirst = false;
                            arbol.setRootElement(nodo);
                    }else{
                            //referrencio al objeto anterior de la pila y
                            //cargo en su lista de hijos el ultimo objeto de la pila
                            //que es el ultimo que se creeo
                            pila.get(pila.size()-2).addChild(pila.get(pila.size()-1));
                            }
                    System.out.println(matcher.group(1));
                } else {
                    //controla los tag con atributos
                    if (matcher.group(2) != null) {
                            //Asingno nombre del tag al tag
                            tag.setQname(matcher.group(2));
                            //creo elatributo del nodo
                            atr = new Atributo();
                            atr.setNombre(matcher.group(3));
                            atr.setValor(matcher.group(4));
                            tag.addAtributo(atr);
                            //seteo al nodo su tag
                            nodo.setTag(tag);
                            //asigano a la pila el nodo creado;
                            pila.add(nodo);
                            sax.startElement(matcher.group(2), atr);
                            // la primera vez agrega el nodo al arbol
                            if (isFirst) {
                                    //arbol = new Arbol();
                                    isFirst = false;
                                    arbol.setRootElement(nodo);
                            }else{
                                    //referrencio al objeto anterior de la pila y
                                    //cargo en su lista de hijos el ultimo objeto de la pila
                                    //que es el ultimo que se creeo
                                    pila.get(pila.size()-2).addChild(pila.get(pila.size()-1));
                            }
                            System.out.println(matcher.group(2));
                    }
                    if (matcher.group(5) != null) {
                        System.out.println(matcher.group(5));
                        sax.endElement(null, null, matcher.group(5));
                        pila.remove(pila.size()-1);
                    }
                }
                if (matcher.group(6) != null) {
                    System.out.println(matcher.group(6));
                    System.out.println(matcher.group(7));
                    arbol.setDocType( matcher.group(6));
                    arbol.setDocInfo(matcher.group(7));
                }
                if (matcher.group(8) != null) {
                    System.out.println("lee el comentario: " + matcher.group(8));
                }
            } catch (IllegalStateException ise) {
                String pat = "<(\\w+)>(.*)</(\\w+)>";
                Pattern patron = Pattern.compile(pat);
        
                String lineaCompleta = doc[countLine - 2].toString()
                        + doc[countLine - 1].toString()
                        + doc[countLine].toString();
               
                Matcher mat = patron.matcher(lineaCompleta);
                mat.find();
                try{
                   // if (mat.matches()){
                    if (mat.group(1).equals(mat.group(3))) {
                        if (mat.group(2) != null) {
                            pila.get(pila.size() - 1).setDato(line);
                            // seteo datos del tag xml.
                            sax.characters(line);
                        }
                    }//}
                }catch (IllegalStateException ex){
                    throw new SAXException(SAXException.Tipo.FATAL_ERROR,"Error de Sintaxis:  "+ line );
                }
            }catch (NumberFormatException e) {
                throw new SAXException(SAXException.Tipo.FATAL_ERROR,"Error de Sintaxis:  "+ line );
            }catch (NullPointerException e) {
                throw new SAXException(SAXException.Tipo.FATAL_ERROR,"Error de Sintaxis:  "+ line );
            }

        }
        if(!pila.isEmpty() || !pila.isEmpty()){
            throw new SAXException(SAXException.Tipo.BAD_FORMED,"El XML se encuentra mal formado: TAG: "+pila.get(0).getData().getQname());
        }
        return arbol;
    }

}
